package ar.edu.ufasta.presupuestos.logica.aplicativo;

import java.sql.ResultSet;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import ar.edu.ufasta.presupuestos.logica.entidades.Cliente;
import ar.edu.ufasta.presupuestos.logica.entidades.articulo.Articulo;
import ar.edu.ufasta.presupuestos.logica.entidades.estados.Anulado;
import ar.edu.ufasta.presupuestos.logica.entidades.estados.EstadoFactory;
import ar.edu.ufasta.presupuestos.logica.entidades.presupuesto.DetallePresupuesto;
import ar.edu.ufasta.presupuestos.logica.entidades.presupuesto.FormaPago;
import ar.edu.ufasta.presupuestos.logica.entidades.presupuesto.Presupuesto;
import ar.edu.ufasta.presupuestos.servicios.ConexionMySQL;
import ar.edu.ufasta.presupuestos.servicios.inventario.InventarioFacade;
import ar.edu.ufasta.presupuestos.servicios.persistencia.ObjectID;
import ar.edu.ufasta.presupuestos.servicios.persistencia.PersistenceFacade;
import ar.edu.ufasta.presupuestos.servicios.presupuesto.PresupuestoServiceFacade;


/**
 * Clase que realiza la logica de la interfaz visual del aplicativo Seccion
 * Presupuestos: - Listado de Presupuestos - Busqueda de 1 Presupuesto - Alta de Presupuesto -
 * Baja de Presupuesto - Modificacion de Presupuesto
 * 
 * @author Carlos Gaspar
 * @version 0.0.0.1 Universidad FASTA
 * 
 */
public class ControladorSeccionPresupuestos extends ControladorGenerico {

	public Presupuesto miPresupuesto;
	private Hashtable<String, Object> parametros;
	private Vector<Cliente> vecClientes;
	private Vector<FormaPago> vecFormaPagos;
	//private Vector<Presupuesto> vecPresupuesto;
	
	/**
	 * Resolver todos los presupuestos posibles - Proceso Batch
	 * 
	 * @return Codigo de resultado de la operacion
	 * @throws Exception
	 * 
	 */
	public int procesarPresupuestos(){
		
		int resul;
		try {
			resul = PresupuestoServiceFacade.getInstancia().resolvePresupuestos();
		} catch (Exception e) {
			e.printStackTrace();
			return Constantes.ERROR_EN_CONSULTA_SQL.getValue();
		}
		return resul;
	}
	
	
	/**
	 * Encontrar todos los registros almacenados ordenados segun una condicion
	 * WHERE
	 * 
	 * @param tabla ->
	 *            Nombre de la tabla a usar
	 * @param ordenLista ->
	 *            Orden en que se devolvera la lista
	 * @param condicion ->
	 *            Condicion a utilizar al seleccionar los datos
	 * @return Lista de entradas encontradas
	 * @throws Exception
	 * 
	 */
	public Vector<Object[]> getRegistrosDonde(int tipo, String tabla,
			String ordenLista, int condicion) throws Exception{
		Vector<Object[]> vec;
		vec = new Vector<Object[]>();
		switch (tipo) {
		case 1:	// Presupuestos 
			vec = buscarPresupuestos(tabla,ordenLista,null);
			break;
		case 2:	// Clientes
			// myList = adminEquipo.search(Cliente.class, "SELECT * FROM
			// CLIENTES");
			vec = buscarClientes(tabla,ordenLista,null);
			break;
		case 3:	// Forma de Pago
			// myList = adminEquipo.search(FormaPago.class, "SELECT * FROM
			// FORMAS_DE_PAGO");
			vec = buscarFormasPagos(tabla,ordenLista,null);
			break;
		case 4: // Detalle de un presupuesto
			vec = buscarDetallePresupuesto(tabla,ordenLista,condicion);
			break;
		default:
			break;
		}
		
		return vec;
	}

	private Vector<Object[]> buscarFormasPagos(String tabla, String ordenLista,
			String condicion) throws Exception {
		Vector<Object[]> vec;
		vec = new Vector<Object[]>();
		vecFormaPagos = new Vector<FormaPago>();
		FormaPago objRecord;
		try {
			ConexionMySQL conn = ConexionMySQL.getInstancia();
			String zQuery = null;
			zQuery = "SELECT * FROM " + tabla;
			if (condicion != null)
				zQuery += "WHERE " + condicion;
			if (ordenLista != null)
				zQuery += "ORDER BY " + ordenLista;
			ResultSet resulset = conn.executeQuery(zQuery);

			while (resulset.next()) {
				// Actualizo listado de objectos del controlador
				objRecord = new FormaPago();
				objRecord.setOid(new ObjectID(resulset.getInt("ID")));
				objRecord.setDescripcion(resulset.getString("descripcion"));
				vecFormaPagos.addElement(objRecord);
				// Devuelvo arreglo de valores para la vista
				Object[] record = new Object[2];
				record[0] = resulset.getInt("ID");
				record[1] = resulset.getString("descripcion");
				vec.addElement(record);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return vec;
	}

	private Vector<Object[]> buscarClientes(String tabla, String ordenLista,
			String condicion) throws Exception {
		Vector<Object[]> vec;
		vec = new Vector<Object[]>();
		vecClientes = new Vector<Cliente>();
		Cliente objRecord;
		try {
			ConexionMySQL conn = ConexionMySQL.getInstancia();
			String zQuery = null;
			zQuery = "SELECT * FROM " + tabla;
			if (condicion != null)
				zQuery += "WHERE " + condicion;
			if (ordenLista != null)
				zQuery += "ORDER BY " + ordenLista;
			ResultSet resulset = conn.executeQuery(zQuery);

			while (resulset.next()) {
				// Actualizo listado de objectos del controlador
				objRecord = new Cliente();
				objRecord.setOid(new ObjectID(resulset.getInt("ID")));
				objRecord.setNombre(resulset.getString("apellido") + ", "+resulset.getString("nombre"));
				vecClientes.addElement(objRecord);
				// Devuelvo arreglo de valores para la vista
				Object[] record = new Object[2];
				record[0] = resulset.getInt("ID");
				record[1] = resulset.getString("apellido")+ ", "+resulset.getString("nombre");
				vec.addElement(record);				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return vec;
	}

	
	private Vector<Object[]> buscarDetallePresupuesto(String tabla,
			String ordenLista, int condicion) throws Exception {
		Vector<Object[]> vec;
		vec = new Vector<Object[]>();
		int articuloCode=0;
		Articulo art;
		PresupuestoServiceFacade presupuestos = PresupuestoServiceFacade.getInstancia();
		InventarioFacade inventario = InventarioFacade.getInstancia();
		miPresupuesto = presupuestos.getPresupuesto(new ObjectID(condicion));
		
		// Devulevo arreglo de valores a la vista
		for (DetallePresupuesto detalle : miPresupuesto.getDetallePresupuesto()) {
			articuloCode = detalle.getArticulo().getIDValue();
			// Obtengo info del articulo
			art = inventario.getArticulo(new ObjectID(articuloCode));
			
			Object[] record = new Object[6];
			record[0] = art.getNombre();
			record[1] = art.getCostoUnitario();
			record[2] = detalle.getCantidad();
			Double total = art.getCostoUnitario() * detalle.getCantidad();
			record[3] = total;
			record[4] = articuloCode;
			record[5] = detalle.getIDValue();
			vec.addElement(record);
		}
		return vec;
	}
	
	private Vector<Object[]> buscarPresupuestos(String tabla,
			String ordenLista, String condicion) throws Exception {
		List<Presupuesto> listado;
		Vector<Object[]> vec;
		vec = new Vector<Object[]>();
		
		PresupuestoServiceFacade presupuestos = PresupuestoServiceFacade.getInstancia();
		listado = presupuestos.getAllPresupuesto();
		
		for (Iterator<Presupuesto> iterator = listado.iterator(); iterator.hasNext();) {
			Presupuesto presupuestoAct = (Presupuesto) iterator.next();
			// Devuelvo arreglo de valores para la vista
			Object[] record = new Object[6];
			record[0] = presupuestoAct.getIDValue(); 
			record[1] = presupuestoAct.getCliente().getApellido()+", "+presupuestoAct.getCliente().getNombre(); 
			record[2] = presupuestoAct.getFechaEmision(); 
			record[3] = presupuestoAct.getEstado().getNombre(); 
			record[4] = presupuestoAct.getTotal(); 
			record[5] = presupuestoAct.getFormaPago().getDescripcion();
			vec.addElement(record);
		}
		
		/*Vector<Object[]> vec;
		vec = new Vector<Object[]>();
		Presupuesto objRecord;
		vecPresupuesto = new Vector<Presupuesto>();
		try {
			ConexionMySQL conn = ConexionMySQL.getInstancia();
			String zQuery = null;
			zQuery = "select p.ID,concat(c.apellido,', ',c.nombre) as 'NOMBRE_CLIENTE',p.fecha_emision,ep.descripcion as 'ESTADO',sum(art.precio) as 'TOTAL',fp.descripcion as 'FPAGO' "
				+ "from presupuestos p join clientes c on p.ID_cliente=c.ID "
				+ "join formas_de_pago fp on p.ID_forma_pago=fp.ID "
				+ "join estados_presupuestos ep on p.ID_estado=ep.ID "
				+ "join detalle_presupuestos dp on p.ID=dp.ID_presupuesto "
				+ "join articulos art on dp.ID_producto=art.ID ";
			if (condicion != null)
				zQuery += "WHERE " + condicion;
			zQuery += " GROUP BY p.ID";
			ResultSet resulset = conn.executeQuery(zQuery);		

			while (resulset.next()) {
				// Actualizo listado de objectos del controlador
				objRecord = new Presupuesto();
				//objRecord.setEstado(resulset.getString("ESTADO"));
				objRecord.setId(new ObjectID(resulset.getInt("ID")));
				objRecord.setFechaEmision(resulset.getDate("fecha_emision"));
				objRecord.setTotal(resulset.getFloat("TOTAL"));
				vecPresupuesto.addElement(objRecord);
				// Devuelvo arreglo de valores para la vista
				Object[] record = new Object[6];
				record[0] = resulset.getInt("ID");
				record[1] = resulset.getString("NOMBRE_CLIENTE");
				record[2] = resulset.getDate("fecha_emision");
				record[3] = resulset.getString("ESTADO");
				record[4] = resulset.getFloat("TOTAL");
				record[5] = resulset.getString("FPAGO");
				vec.addElement(record);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}*/
		return vec;
	}
	
	/**
	 * Encuentra un presupuesto y todos sus elementos relacionados
	 * 
	 * @param code -> ID del presupuesto a traer de la base de datos
	 * @return void
	 * @throws Exception
	 * 
	 */
	public Hashtable<String, Object> consultaPresupuesto(String code) throws Exception {
		Hashtable<String, Object> presupuestoMap = new Hashtable<String, Object>();
		try {
			PresupuestoServiceFacade presupuestos = PresupuestoServiceFacade.getInstancia();
			miPresupuesto = presupuestos.getPresupuesto(new ObjectID(Integer.valueOf(code)));
			
			presupuestoMap.put("vCliente", miPresupuesto.getCliente().getApellido()+", "+miPresupuesto.getCliente().getNombre());
			presupuestoMap.put("vFechaEmision", miPresupuesto.getFechaEmision());
			presupuestoMap.put("vId", miPresupuesto.getIDValue());
			presupuestoMap.put("vTotal", miPresupuesto.getTotal());
			presupuestoMap.put("vFormaPago", miPresupuesto.getFormaPago().getDescripcion());
			presupuestoMap.put("vEstado", miPresupuesto.getEstado().getNombre());
			presupuestoMap.put("vIdEstado", miPresupuesto.getEstado().getCode());
						
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return presupuestoMap;
	}
	
	/**
	 * Inserta un nuevo presupuesto en la base de datos
	 * 
	 * @param params ->
	 *            Parametros del presupuesto a insertar
	 * @return void
	 * @throws Exception
	 * 
	 */
	public int insertaPresupuesto(String nombrePK, Hashtable<String, Object> params, Vector<Object[]> items) {
		Boolean resul_val;
		int ret;
		int id_producto;
		int cantidad;
		Double total=0.0;
		Double precioArticulo=0.0;
		this.parametros = params;
		miPresupuesto = new Presupuesto();
		Cliente cliente = new Cliente();
		FormaPago fpago = new FormaPago();
		miPresupuesto.setCliente(cliente);
		miPresupuesto.setFormaPago(fpago);
		
		miPresupuesto.getCliente().setOid(new ObjectID((Integer) parametros.get("vCliente")));
		miPresupuesto.getCliente().setNombre((String) parametros.get("vClienteNombre"));
		miPresupuesto.getFormaPago().setOid(new ObjectID((Integer) parametros.get("vFormaPago")));
		miPresupuesto.getFormaPago().setDescripcion((String) parametros.get("vFormaPagoNombre"));
		
		for (Iterator<Object[]> iterator = items.iterator(); iterator.hasNext();) {
			Object[] objects = (Object[]) iterator.next();
			id_producto = (Integer)objects[4];
			cantidad = (Integer)objects[2];
			miPresupuesto.agregarNuevoDetalle(id_producto, cantidad,-1);
			precioArticulo = InventarioFacade.getInstancia().getArticulo(new ObjectID(id_producto)).getCostoUnitario();
			total = total + (cantidad * precioArticulo);
		}
		miPresupuesto.setTotal(total);
		miPresupuesto.setEstado(EstadoFactory.getInstance().getEstado(1));
		miPresupuesto.setFechaEmision(new Date());
		
		PresupuestoServiceFacade presupuestos = PresupuestoServiceFacade.getInstancia();
		resul_val = presupuestos.addPresupuesto(miPresupuesto);
		if (resul_val == true)
			ret = 0;
		else
			ret = -1;
		return ret;
	}
	
	
	/**
	 * Elimina un presupuesto en la base de datos
	 * 
	 * @param params -> Parametros del presupuesto a eliminar
	 * @return resultCode
	 * @throws Exception 
	 */
	public int eliminaPresupuesto(Hashtable<String, Object> params){
		Boolean resul_val;
		int ret;
		this.parametros = params;
		miPresupuesto = new Presupuesto();
		miPresupuesto.setOid(new ObjectID((Integer)parametros.get("vID")));
		PresupuestoServiceFacade presupuestos = PresupuestoServiceFacade.getInstancia();
		resul_val = presupuestos.removePresupuesto(miPresupuesto.getOid());
		if (resul_val == true)
			ret = 0;
		else
			ret = -1;
		return ret;
	}
	
	/**
	 * Modifica un presupuesto de la base de datos
	 * @param params -> Parametros del presupuesto a modificar
	 * @return resultCode
	 * @throws Exception
	 */
	public int modificaPresupuesto(Hashtable<String, Object> params, Vector<Object[]> items){
		Boolean resul_val;
		int ret;
		int id_producto;
		int cantidad;
		int IDDetalle;
		Double total=0.0;
		Double precioArticulo=0.0;
		this.parametros = params;
		miPresupuesto = new Presupuesto();
		miPresupuesto.setOid(new ObjectID((Integer)parametros.get("vID")));
		Integer estadoID = (Integer)parametros.get("vIdEstado");
		miPresupuesto.setEstadoInstance(estadoID);
		Cliente cliente = new Cliente();
		FormaPago fpago = new FormaPago();
		miPresupuesto.setCliente(cliente);
		miPresupuesto.setFormaPago(fpago);
		miPresupuesto.getCliente().setOid(new ObjectID((Integer) parametros.get("vCliente")));
		miPresupuesto.getCliente().setNombre((String) parametros.get("vClienteNombre"));
		miPresupuesto.getFormaPago().setOid(new ObjectID((Integer) parametros.get("vFPago")));
		miPresupuesto.getFormaPago().setDescripcion((String) parametros.get("vFormaPagoNombre"));
		for (Iterator<Object[]> iterator = items.iterator(); iterator.hasNext();) {
			Object[] objects = (Object[]) iterator.next();
			id_producto = (Integer)objects[4];
			cantidad = (Integer)objects[2];
			IDDetalle = (Integer)objects[5];
			miPresupuesto.agregarNuevoDetalle(id_producto, cantidad, IDDetalle);
			precioArticulo = InventarioFacade.getInstancia().getArticulo(new ObjectID(id_producto)).getCostoUnitario();
			total = total + (cantidad * precioArticulo);
					
		}
		miPresupuesto.setTotal(total);
		SimpleDateFormat format = new SimpleDateFormat();
		ParsePosition posicion = new ParsePosition(0);
		Date fechaEmision = format.parse((String)parametros.get("vFechaEmision"), posicion);
		miPresupuesto.setFechaEmision(fechaEmision);
		
		PresupuestoServiceFacade presupuestos = PresupuestoServiceFacade.getInstancia();
		resul_val = presupuestos.updatePresupuesto(miPresupuesto);
		if (resul_val == true)
			ret = 0;
		else
			ret = -1;
		return ret;
	}


	
	/**
	 * Anula un presupuesto de la base de datos
	 * @param params -> Parametros del presupuesto a anular
	 * @return resultCode
	 * @throws Exception
	 */
	public int anulaPresupuesto(Hashtable<String, Object> params) {
		int ret;
		this.parametros = params;
		
		miPresupuesto = (Presupuesto)PersistenceFacade.getInstance().get(new ObjectID((Integer)params.get("vID")), Presupuesto.class);
		
		if (miPresupuesto == null){
			return -1;
		}else{
			miPresupuesto.setEstado(new Anulado());
			PresupuestoServiceFacade.getInstancia().updatePresupuesto(miPresupuesto);
			ret = 0;
		}		
		return ret;
	}
	
	
	
}
